import qasync
from PySide6.QtCore import QObject, Signal, Property, Slot
from PySide6.QtQml import QmlElement

from src.library import SearchLibrary, Source
from src.model import MusicListModel
from src.common.signal_bus import SignalBus

QML_IMPORT_NAME = "Backend"
QML_IMPORT_MAJOR_VERSION = 1


@QmlElement
class SearchTipViewModel(QObject):
    tipSearchWordsChanged = Signal()

    def __init__(self):
        super().__init__()
        self._signalBus = SignalBus()
        self.search_api = SearchLibrary()
        self._tip_search_words = []

    @Property(list, notify=tipSearchWordsChanged)
    def tipSearchWords(self):
        return self._tip_search_words

    @Slot()
    def clearTipSearchWords(self):
        self._tip_search_words.clear()
        self.tipSearchWordsChanged.emit()

    @qasync.asyncSlot(str)
    async def getTipSearchWords(self, keyword):
        res = await self.search_api.get_tip_search(Source.MERGE, keyword)
        code = res.get("code")
        if code != 200:
            return
        self._tip_search_words = res.get("list")
        self.tipSearchWordsChanged.emit()


@QmlElement
class SearchPageViewModel(QObject):
    loadingSearchResult = Signal(bool, arguments=["loading"])

    totalResultChanged = Signal()
    loadingMoreChanged = Signal()
    loadingAllFinishedChanged = Signal()

    def __init__(self):
        super().__init__()
        self._signalBus = SignalBus()
        self._bind_bus()
        self.search_api = SearchLibrary()
        self._loading_more = False
        self._loading_all_finished = False
        self._current_source = Source.KU_WO
        self._current_search_keyword = ""
        self._next_page = 1
        self._total_result = 0
        self._music_list_model: MusicListModel = MusicListModel([])

    def _bind_bus(self):
        pass

    @Property(bool, notify=loadingAllFinishedChanged)
    def loadingAllFinished(self):
        return self._loading_all_finished

    @loadingAllFinished.setter
    def loadingAllFinished(self, value):
        if self._loading_all_finished == value:
            return
        self._loading_all_finished = value
        self.loadingAllFinishedChanged.emit()

    @Property(bool, notify=loadingMoreChanged)
    def loadingMore(self):
        return self._loading_more

    @loadingMore.setter
    def loadingMore(self, value):
        if self._loading_more == value:
            return
        self._loading_more = value
        self.loadingMoreChanged.emit()

    @Property(int, notify=totalResultChanged)
    def totalResult(self):
        return self._total_result

    @totalResult.setter
    def totalResult(self, value):
        if self._total_result == value:
            return
        self._total_result = value
        self.totalResultChanged.emit()

    @Property(MusicListModel, constant=True)
    def musicListModel(self):
        return self._music_list_model

    @Slot(int)
    def playMusic(self, index):
        music = self._music_list_model.musics[index]
        self._signalBus.addMusic.emit(music, True)

    @Slot(int)
    def addMusic(self, index):
        music = self._music_list_model.musics[index]
        self._signalBus.addMusic.emit(music, False)

    @Slot(int)
    def downloadMusic(self, index):
        print("download music", self._music_list_model.musics[index])

    @qasync.asyncSlot(str)
    async def search(self, keyword):
        self._current_search_keyword = keyword
        self._next_page = 1
        self.loadingSearchResult.emit(True)
        res = await self.search_api.search(self._current_source, self._current_search_keyword,
                                           page=self._next_page)
        music_list, search_total = res.get("list"), res.get("total")
        self._music_list_model.reset(music_list)
        self.totalResult = search_total
        self._next_page = 2
        self.loadingSearchResult.emit(False)

    @qasync.asyncSlot()
    async def loadMore(self):
        if self._loading_more or self._loading_all_finished:
            return
        if self._music_list_model.count >= self._total_result:
            self.loadingAllFinished = True
            return

        self.loadingMore = True
        res = await self.search_api.search(self._current_source, self._current_search_keyword,
                                           page=self._next_page)
        music_list = res.get("list")
        if not music_list:
            self.loadingAllFinished = True
            self.loadingMore = False
            return
        self._music_list_model.extend(music_list)
        self.loadingMore = False
        self._next_page += 1
